package com.ma.a11;

import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @ClassName JdkProxyDemo
 * @Author: mayongqiang
 * @DATE 2022/4/7 23:00
 * @Description: Java的代理
 */
/*
    jdk 动态代理要求目标必须实现接口，生成的代理类实现相同接口，因此代理与目标之间是平级兄弟关系
 */
public class JdkProxyDemo {
    // 1、JDK 只能接受接口代理
    // 2、cglib
    public static void main(String[] args) throws IOException {

        //目标对象
        Target target = new Target();


        // 代理类是在运行期间直接生成代理类的字节码，需要被加载后运行
        ClassLoader loader = JdkProxyDemo.class.getClassLoader();
        // InvocationHandler  对代理类实现的行为进行封装  当代理类的方法被调用时，执行invoke()
        Foo proxy = (Foo) Proxy.newProxyInstance(loader, new Class[]{Foo.class}, new InvocationHandler() {
            @Override
            public Object invoke(Object p, Method method, Object[] args1) throws Throwable {
                System.out.println("before");  //前置增强
                // 目标.方法(参数)
                // 方法.invoke(目标,参数)
                Object result = method.invoke(target, args1);

                System.out.println("after"); //后置增强
                // 代理返回目标方法执行的结果
                return result;
            }
        });
        System.out.println(proxy.getClass());
        proxy.foo();
        System.in.read();
    }

    interface Foo {
        void foo();
    }

    static class Target implements Foo {

        @Override
        public void foo() {
            System.out.println("target foo");
        }
    }
}
